package com.hibase.core.rule.utils;


import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.sql.visitor.functions.Char;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.hibase.common.exception.HibaseAssert;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 描述:
 *
 * @author li-wei-hua
 * @date 2020-03-20 16:52
 */
public class HiBaseSqlUtils {
    private static final String REGX = "\\#\\{([^{}]+?)\\}";

    public static String disposeSqlLimit50(String sql, Object... args) {
        if (args[0] instanceof Map) {
            return disposeSqlByMap(sql, (Map<String, Object>) args[0]);
        } else {
            return MessageFormat.format(sql, args != null ? Arrays.stream(args).map(String::valueOf).
                    map(p -> StrUtil.center(p, p.length() + 2, "'")).toArray() : null).concat(" limit 50");
        }
    }

    public static String disposeSql(String sql, Object... args) {
        if (args[0] instanceof Map) {
            return disposeSqlByMap(sql, (Map<String, Object>) args[0]);
        } else {
            return MessageFormat.format(sql, args != null ? Arrays.stream(args).map(String::valueOf).
                    map(p -> StrUtil.center(p, p.length() + 2, "'")).toArray() : null);
        }
    }

    public static Object getSqlStatementParameters(String sql, String parameters) {

        if (StrUtil.isBlank(sql) || StrUtil.isBlank(parameters)) {
            return null;
        }
        Pattern pattern = Pattern.compile(REGX);
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            return JSON.parseObject(parameters);
        } else {
            return JSON.parseObject(parameters).values().toArray();
        }
    }


    /**
     * SQL 处理
     *
     * @param sql    原始SQL
     * @param params 查询条件
     * @return 返回或处理后的SQL
     * @remark sql模板格式：#{AND LOC.WAREHOUSE_ID = [仓库序号] }
     */
    public static String disposeSqlByMap(String sql, Map<String, Object> params) {
        Pattern pattern = Pattern.compile(REGX, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(sql);
        StringBuffer sqlStatement = new StringBuffer();
        int last = -1;
        while (matcher.find()) {
            String sqlCondition = getSqlCondition(matcher.group(0));
            sqlCondition = getSqlStatement(sqlCondition, params);
            matcher.appendReplacement(sqlStatement, sqlCondition);
            last = matcher.end();
        }
        if (sqlStatement.length() > 0) {
            sqlStatement.append(sql.substring(last));
            return sqlStatement.toString();
        }


        return sql;
    }


    /**
     * 构造动态SQL
     *
     * @param sqlCondition
     * @param conditionMap
     * @return
     */
    public static String getSqlStatement(String sqlCondition, Map<String, Object> conditionMap) {
        // #{AND LOC.WAREHOUSE_ID1 = [仓库序号1] }  非必填
        // #{AND LOC.WAREHOUSE_ID1 = *[仓库序号1] }  必填

        final String regx = "\\*?\\[(.*?)]";
        Pattern pattern = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(sqlCondition);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String param = matcher.group(0);

            String paramKey = null;
            if (param.indexOf("*[") == 0) {
                paramKey = param.substring(param.indexOf("*[") + 1, param.lastIndexOf("]"));
                HibaseAssert.isTrue(conditionMap.containsKey(paramKey),
                        "SqlStatement Parameter:" + sqlCondition + "【" + paramKey + "】not match.");
            } else {
                // 非必填项执行移除该条件
                paramKey = param.substring(param.indexOf("[") + 1, param.lastIndexOf("]"));
                if (!conditionMap.containsKey(paramKey)) {
                    continue;
                }
            }

            Object paramValue = conditionMap.get(paramKey);
            // 字符串处理
            if (paramValue instanceof String || paramValue instanceof Date || paramValue instanceof Char) {
                paramValue = CharUtil.SINGLE_QUOTE + paramValue.toString() + CharUtil.SINGLE_QUOTE;
            }
            matcher.appendReplacement(sb, paramValue.toString());
        }

        return sb.toString();
    }


    public static String getSqlCondition(String sqlCondition) {
        // 移除 ${ 、} 标志符
        sqlCondition = ReUtil.delFirst("\\#\\{", sqlCondition);
        return StrUtil.sub(sqlCondition, 0, sqlCondition.lastIndexOf(StrUtil.DELIM_END));
    }

    public static void main(String[] args) {
        String[] sqlArray = new String[]{
                "SELECT * FROM TABLE_NAME WHERE 1=1 #{AND LOC.WAREHOUSE_ID1 = [仓库序号1] } #{AND LOC.WAREHOUSE_ID2 = [仓库序号2] };",
                "SELECT * FROM TABLE_NAME WHERE 1=1 #{AND LOC.WAREHOUSE_ID1 = [仓库序号1] } #{AND LOC.WAREHOUSE_ID2 = [仓库序号2] };",
                "SELECT * FROM TABLE_NAME WHERE 1=1 #{AND LOC.WAREHOUSE_ID1 = [仓库序号1] } #{AND LOC.WAREHOUSE_ID2 = [仓库序号2] } and a=b;",
        };

        for (int i = 0; i < sqlArray.length; i++) {
            Map<String, Object> params = Maps.newHashMap();
            params.put("仓库序号1", "20220211");
            params.put("仓库序号2", 21);
            String sqlStatement = disposeSqlByMap(sqlArray[i], params);
            System.out.println(sqlStatement);
        }


    }

}

